package cn.gwm.flink.streaming.beans;

import cn.gwm.flink.streaming.constant.BaseFields;
import cn.gwm.flink.streaming.constant.VehicleType;
import cn.gwm.flink.streaming.ods.ModelHandle;
import cn.gwm.flink.streaming.ods.model.StandardFieldConf;
import cn.gwm.utils.ConfigLoader;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.UnicodeUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.db.Db;
import cn.hutool.db.ds.DSFactory;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: liangguang
 * @Date: 2022/10/10
 * @Description: 1. 读取 配置文件 字段，保证顺序性
 * 2. 提供只读集合，供 使用
 */
public class BeanSource {
    /**
     * 配置文件 字段 分隔符
     */
    public final static String separator = StrUtil.SPACE + "#";

    private static final Map<String, List<String>> sourceMap = new ConcurrentHashMap<>();


    /**
     * 获取 转化字段集合
     *
     * @param source
     * @return
     */
    public static List<String> sourceList(SourceEnum source) {
        List<String> list = sourceMap.get(source.getSourceName());
        if (CollectionUtil.isEmpty(list)) {
            List<String> sourceList = FileUtil.readUtf8Lines(ResourceUtil.getResource(source.getSourcePro()));
            ArrayList<String> arrayList = CollectionUtil.newArrayList();
            for (String str : sourceList) {
                arrayList.add(str.split(separator)[0]);
            }
            list = Collections.unmodifiableList(arrayList);
            sourceMap.put(source.getSourceName(), list);
        }
        return list;
    }

    /**
     * 获取 补充默认值的 json 数据
     *
     * @param source
     * @param sourceEnum
     * @return
     */
    public static JSONObject transJson(JSONObject source, SourceEnum sourceEnum) {
        List<String> list = BeanSource.sourceList(sourceEnum);
        JSONObject result = JSONUtil.createObj();
        list.forEach(key -> {
            String v = source.getStr(key);
            if (!source.containsKey(key) || StrUtil.DASHED.equals(v)) {
                result.set(key, BaseFields.defaultVal);
            } else {
                result.set(key, v);
            }
        });
        return result;
    }

    public static String getSchema(SourceEnum sourceEnum) {
        List<String> list = sourceList(sourceEnum);
        return getSchema(list);
    }
    public static String getSchema(List<String> list) {
        String schema = "struct<";
        for (String str : list) {
            if (!BaseFields.PARTITION_KEY.equals(str)) {
                schema = schema + str + ":string,";
            }
        }
        schema = schema.substring(0, schema.length() - 1);
        schema += ">";
        return schema;

    }

    @Getter
    @AllArgsConstructor
    public enum SourceEnum {
        // es13 经纬度补充数据
        es13LocationReplenishSource("es13LocationReplenishSource", "source/es13LocationReplenishSource.properties"),
        ES13evFullFieldSource("ES13evFullFieldSource", "source/ES13evFullFieldSource.properties"),

        // v71 phev
        phevV71LongSource("phevV71LongSource", "source/v71PhevLongSource.properties"),
        phevV71ShortSource("phevV71ShortSource", "source/v71PhevShortSource.properties"),
        phevV71LocationSource("phevV71LocationSource", "source/v71PhevLocationSource.properties"),

        // es13
        evEs13LongSource("evEs13LongSource", "source/es13LongSource.properties"),
        evEs13LongSourceBuShu("evEs13LongSourceBuShu", "source/es13LongSourceBuShu.properties"),
        evEs13ShortSource("evEs13ShortSource", "source/es13ShortSource.properties"),
        evEs13LocationSource("evEs13LocationSource", "source/es13LocationSource.properties"),

        // dwd
        evFullFieldSource("evFullFieldSource", "source/dwdEvFullFieldSource.properties"),
        phevFullFieldSource("phevFullFieldSource", "source/dwdPhevFullFieldSource.properties"),

        // ev - charge  不区分 ev和 phev
        evChargeSummar("evChargeSummar", "source/chargeSummar.properties"),
        evChargeDetail("evChargeDetail", "source/chargeDetail.properties"),
        evChargeMultidimensional("evChargeMultidimensional", "source/chargeMultidimensional.properties"),

        chargeFavourable("chargeFavourable", "source/chargeFavourable.properties"),

        //ec24 闪电猫
        evEc24Intranet("evEc24Intranet", "source/evEc24Intranet.properties"),
        //es13芭蕾猫
        evEs13Intranet("evEs13Intranet", "source/evEs13Intranet.properties"),
        evV71Intranet("evV71Intranet", "source/evV71Intranet.properties"),
        evEs24Intranet("evEs24Intranet", "source/evEs24Intranet.properties"),
        gpsIntranet("gpsIntranet", "source/gpsIntranet.properties"),
        remoteRequest("remoteRequest", "source/remoteRequest.properties"),
        gpsIntranetFlag("gpsIntranetFlag", "source/gpsIntranetFlag.properties"),
        gpsIntranetV71Ali("gpsIntranetV71Ali", "source/gpsIntranetV71Ali.properties"),
        evOdsTh("evOdsTh", "source/evOds.properties"),
        evOdsGps("evOdsGps", "source/evOdsGps.properties"),
        evOdsAli("evOdsAli", "source/evOdsAli.properties"),
        phevOdsTh("phevOdsTh", "source/phevOds.properties"),
        phevOdsGps("phevOdsGps", "source/phevOdsGps.properties"),
        testEs13Gps("testEs13Gps", "source/testEs13Gps.properties"),

        chargeReserve("chargeReserve", "source/chargeReserve.properties"),
        ;

        private String sourceName;
        private String sourcePro;

    }

    private static List<String> list;
    private static List<String> nameList;
    static {
        list = new ArrayList<>();
        nameList = new ArrayList<>();
        try {
            Db.use(DSFactory.get(ConfigLoader.get("mysql.group.db.config")))
                    .find(StandardFieldConf.getEntityWhere(), StandardFieldConf.class).stream()
                    .filter(data -> ModelHandle.BIZ_TYPE_ODS.equals(data.getBizType())
                            &&Integer.parseInt(data.getState())>0
                            &&(("1".equals(data.getVersion())
                            &&"ERROR".equals(data.getVehicletype()))
                            ||"BASE".equals(data.getVehicletype())))
                    .sorted(new Comparator<StandardFieldConf>() {
                        @Override
                        public int compare(StandardFieldConf o1, StandardFieldConf o2) {
                            return Integer.parseInt(o1.getId())-Integer.parseInt(o2.getId());
                        }
                    })
                    .forEach(data -> {
                        list.add(data.getSemaphore());
                        nameList.add(data.getSemaphoreName());
                    });
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
//        create1();
//        create2();
//        create3();
//        create4();
//        create5();
//        create6();
//        create7();
//        create8();
//        createChargeReserve();
//        System.out.println(getSchema(SourceEnum.phevV71LongSource));
//        createHive("`vaas_ods`.`ods_hub_gps_p03`",
//                SourceEnum.gpsIntranet,
//                "p03经纬度工况", "/external/data/ods/hub/gps/ods_gps_p03");
//        String model = "p03";
//        BeanSource.createHive("`vaas_ods`.`ods_hub_can_"+model+"`", model+"长工况数据", "/external/data/ods/hub/can/ods_can_"+model,list,nameList);
//        getSchema(semaphoreList);

        List<String> stringList = sourceList(SourceEnum.evChargeDetail);
        stringList.forEach(System.out::println);

    }

    /**
     * @return void
     * @Author xzh
     * @Description 阿里云es13 长工况，orc压缩存储，表结构创建语句
     * @Date 2023/1/30 11:16
     * @Param []
     **/
    public static void create11() {
        createHive("`vaas_ods`.`ods_can_orc_txt_es13`",
                SourceEnum.evOdsTh,
                "es13长工况数据", "/external/data/odsOrcTxt/es13_long_source");
    }

    public static void create12() {
        createHive("`vaas_ods`.`ods_gps_orc_txt_es13`",
                SourceEnum.gpsIntranet,
                "es13短工况数据", "/external/data/odsOrcTxt/es13_location_source");
    }

    public static void create13() {
        createHive("`vaas_ods`.`ods_can_orc_txt_v71`",
                SourceEnum.phevOdsTh,
                "v71phev长工况数据", "/external/data/odsOrcTxt/v71phev_long_source");
    }

    public static void create14() {
        createHive("`vaas_ods`.`ods_gps_orc_txt_v71`",
                SourceEnum.gpsIntranet,
                "v71phev短工况数据", "/external/data/odsOrcTxt/v71phev_location_source");
    }


    public static void create1() {
        createHive("`vaas_ods`.`ods_intranet_can_es13_source`",
                SourceEnum.evEs13Intranet,
                "es13芭蕾猫源数据", "/external/data/ods/ods_intranet_es13_source");
    }

    public static void create2() {
        createHive("`vaas_ods`.`ods_intranet_gps_es13_source`",
                SourceEnum.gpsIntranet,
                "es13芭蕾猫GPS源数据", "/external/data/ods/ods_intranet_gps_es13_source");
    }

    public static void create3() {
        createHive("`vaas_ods`.`ods_intranet_can_v71_source`",
                SourceEnum.evV71Intranet,
                "v71-phev源数据", "/external/data/ods/ods_intranet_v71_source");
    }

    public static void create4() {
        createHive("`vaas_ods`.`ods_intranet_gps_v71_source`",
                SourceEnum.gpsIntranet,
                "v71-phevGPS源数据", "/external/data/ods/ods_intranet_gps_v71_source");
    }

    public static void create5() {
        createHive("`vaas_ods`.`ods_intranet_can_es24_source`",
                SourceEnum.evEs24Intranet,
                "es24朋克猫源数据", "/external/data/ods/ods_intranet_es24_source");
    }

    public static void create6() {
        createHive("`vaas_ods`.`ods_intranet_gps_es24_source`",
                SourceEnum.gpsIntranet,
                "es24朋克猫GPS源数据", "/external/data/ods/ods_intranet_gps_es24_source");
    }

    public static void create7() {
        createHive("`vaas_ods`.`ods_intranet_can_ec24_source`",
                SourceEnum.evEc24Intranet,
                "ec24闪电猫源数据", "/external/data/ods/ods_intranet_ec24_source");
    }

    public static void create8() {
        createHive("`vaas_ods`.`ods_intranet_gps_ec24_source`",
                SourceEnum.gpsIntranet,
                "ec24闪电猫GPS源数据", "/external/data/ods/ods_intranet_gps_ec24_source");
    }

    public static void createChargeReserve() {
        createHiveText("`vaas_dws`.`dws_charge_reserve`",
                SourceEnum.chargeReserve,
                "预约充电dws表", "/external/data/dws/dws_charge_reserve");
    }

    public static void createHive(String hiveName, String tableNameDesc, String location,List<String> sourceList,List<String> nameList) {
        System.out.println("CREATE EXTERNAL TABLE IF NOT EXISTS " + hiveName + " (");
//        List<String> sourceList = FileUtil.readUtf8Lines(sourceEnum.getSourcePro());
        for(int i=0;i<sourceList.size();i++){
            String[] split = sourceList.get(i).split(separator);
            if (!"datedt".equals(split[0])) {
                if(i<sourceList.size()-1){
                    System.out.println("`" + split[0] + "` string COMMENT '"+nameList.get(i)+"',");
                }else{
                    System.out.println("`" + split[0] + "` string COMMENT '"+nameList.get(i)+"'");
                }
            }
        }
        System.out.println(")");
        System.out.println("COMMENT '" + tableNameDesc + "'");
        System.out.println("PARTITIONED BY (`datedt` string COMMENT '数据日期')");
        System.out.println("stored as orc");
//        System.out.println("ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t' ");
        System.out.println("location '" + location + "'");
        System.out.println("tblproperties(\"orc.compress\"=\"SNAPPY\");");
    }

    public static void createHive(String hiveName, BeanSource.SourceEnum sourceEnum, String tableNameDesc, String location) {
        System.out.println("CREATE EXTERNAL TABLE IF NOT EXISTS " + hiveName + " (");
        List<String> sourceList = FileUtil.readUtf8Lines(sourceEnum.getSourcePro());
//        sourceList.forEach(item -> {
//            String[] split = item.split(separator);
//            String line = "`" + split[0] + "` string" + (VehicleType.VehicleType.equals(split[0]) ? "" : " ,");
//            if (!"datedt".equals(split[0])) {
//                System.out.println(line);
//            }
//        });
        for (int i=0;i<sourceList.size();i++){
            String[] split = sourceList.get(i).split(separator);
            if (!"datedt".equals(split[0])) {
                if(i<sourceList.size()-1){
                    System.out.println("`" + split[0] + "` string,");
                }else{
                    System.out.println("`" + split[0] + "` string");
                }
            }
        }
        System.out.println(")");
        System.out.println("COMMENT '" + tableNameDesc + "'");
        System.out.println("PARTITIONED BY (`datedt` string COMMENT '数据日期')");
        System.out.println("stored as orc");
//        System.out.println("ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t' ");
        System.out.println("location '" + location + "'");
        System.out.println("tblproperties(\"orc.compress\"=\"SNAPPY\");");
    }

    public static void createHiveText(String hiveName, BeanSource.SourceEnum sourceEnum, String tableNameDesc, String location) {
        System.out.println("\t");
        System.out.println("CREATE EXTERNAL TABLE IF NOT EXISTS " + hiveName + " (");
        List<String> sourceList = FileUtil.readUtf8Lines(sourceEnum.getSourcePro());
        for (int i = 0; i < sourceList.size(); i++) {
            String item = sourceList.get(i);
            if (item.startsWith("#") || StringUtils.isBlank(item)) {
                continue;
            }
            String[] split = item.split(separator);
            String key = split[0];
            String line = "`" + key + "` ";
            if (split.length >= 2) {
                String type = split[1];
                if (type.contains("BigDecimal")) {
                    type = type.replace("BigDecimal", "decimal");
                }
                if (type.equals("Integer")) {
                    type = "int";
                }
                if (type.equals("Long")) {
                    type = "bigint";
                }
                if (type.equals("String")) {
                    type = "string";
                }
                line += type;
            }
            if (split.length >= 3) {
                String comment = split[2];
                line += " COMMENT " + "'" + UnicodeUtil.toString(comment) + "'";
            }
            if (sourceList.size() - 1 != i) {
                line += ",";
            }
            System.out.println(line);

        }
        System.out.println(")");
        System.out.println("COMMENT '" + tableNameDesc + "'");
        System.out.println("PARTITIONED BY (`datedt` string COMMENT '数据日期')");
        System.out.println("ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t' ");
        System.out.println("location '" + location + "';");
        System.out.println("\t");
        System.out.println("\t");

    }
}
